#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Zhangcl
import pika
import uuid
import re
import random
import threading

class FibonacciRpcClient(object):
    def __init__(self,ip):
        try:
            self.connection = pika.BlockingConnection(pika.ConnectionParameters(
                host=ip))
        except Exception as e:
            print('ip地址不正确！')
            exit()
        self.channel = self.connection.channel()
        self.channel.exchange_declare('direct_logs','direct')
        #定义一个广播类型，direct: 通过routingKey和exchange决定的那个唯一的queue可以接收消息

        result = self.channel.queue_declare(exclusive=True)
        # #不指定queue名字,rabbit会随机分配一个名字,exclusive=True会在使用此queue的消费者断开后,自动将queue删除
        self.callback_queue = result.method.queue

        self.channel.basic_consume(self.on_response, no_ack=True,
                                   queue=self.callback_queue)

    def on_response(self, ch, method, props, body):
        if self.corr_id == props.correlation_id: #发送的id和接收到的ip匹配时，才是正确的返回结果
            self.response = body

    def call(self,n,ip,ip_bake_message):
        self.response = None
        self.corr_id = str(uuid.uuid4())
        self.channel.basic_publish(exchange='direct_logs',
                                   routing_key = ip,#绑定关键字
                                   properties=pika.BasicProperties(
                                       reply_to=self.callback_queue,#将等下需要服务端返回的queue名和匹配id发送给服务端
                                       correlation_id=self.corr_id,
                                   ),
                                   body=n)
        while self.response is None:
            self.connection.process_data_events() #非阻塞接受信息
        else:
            message_back = self.response
            message_back_de = message_back.decode()
            ip_bake_message[str(ip)] = str(message_back_de) #将对应ip的执行返回结果存入对应ip字典


task_group={}
while True:
    input_cmd=input('>>>>')
    if input_cmd.startswith('check_task'):
        cmd_task = input_cmd.split()
        task_id = cmd_task[-1] #获取taskID，根据ID获取之前执行命令返回的内容
        if task_id in task_group:
            for key in task_group:
                if key == task_id:
                    for show in task_group[key]:
                        print('===============%s===============' %show)
                        print(task_group[key][show])
        else:
            print('taskID不存在！')
    elif input_cmd.startswith('run'):
        pattern = re.compile('"(.*)"') #匹配出“”中输入的命令
        cmd = "".join(pattern.findall(input_cmd)) #取出需要执行的命令
        ip_list = re.findall(r'\d+.\d+.\d+.\d+',input_cmd) #获取需要执行的ip
        guess = ''.join([str(i) for i in random.sample(range(0, 9), 5)]) #生成一个随机的5位数的taskID，执行命令后返回
        task_group[guess] = {}
        ip_back_message = {}
        print('task id:',guess)
        for ip in ip_list: #循环需要执行的ip列表
            fibonacci_rpc = FibonacciRpcClient(ip)
            ip_back_message[ip]= None #生成一个ip对应的返回结果字典
            t = threading.Thread(target=fibonacci_rpc.call,args=(cmd, ip, ip_back_message)) #生成一个线程
            t.start() #启动线程
            task_group[guess]=ip_back_message #将命令执行结果保存
    else:
        print('输入错误！')

